home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sounds Terrific 2
/
Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso
/
archives
/
amiga
/
amichord.lha
/
AmiChord
/
src
/
chord.c
next >
Wrap
C/C++ Source or Header
|
1995-04-09
|
25KB
|
782 lines
#include "chord.h"
unsigned char versiontag[] = "\0$VER: AmiChord 1.2 (" __DATE__ ")";
FILE *source_fd;
FILE *toc_file = NULL; /* optional table of contents file */
unsigned char
text_line[MAXLINE], /* Lyrics Buffer */
chord[MAXTOKEN], /* Buffer for the name of the chord */
title1[MAXLINE]; /* Holds the first title line */
char
source[MAXTOKEN],
directive[MAXTOKEN], /* Buffer for the directive */
mesg[MAXTOKEN];
char
i_input; /* Input line pointer */
char
*text_font = DEF_TEXT_FONT, /* Default font for text */
*chord_font = DEF_CHORD_FONT, /* Default font for chord */
*used_fonts[MAXFONTS][MAXLINE],
*current_file,
*chord_line[MAXLINE];
char *notes[7] = { "C", "D", "E", "F", "G", "A", "B" };
int
c, /* Current character in input file */
i_chord, /* Index to 'chord' */
i_directive, /* Index to 'directive' */
i_text, /* Index to 'text_line' */
in_chord, /* Booleans indicating parsing status */
lyrics_only = FALSE,
auto_space = FALSE, /* applies lyrics_only when no chords */
left_foot_odd = -1, /* -1 for all page numbers on the right */
/* 0 for odd page numbers on the right */
/* 1 for odd page numbers on the left */
number_all = FALSE, /* number the first page (set with -p 1) */
page_label = 1, /* page number for footers and index */
i_chord_ov, /* Overflow Booleans */
i_directive_ov = FALSE,
i_text_ov = FALSE,
in_directive = FALSE,
in_chordrc = FALSE,
in_chorus = FALSE,
has_directive = FALSE,
has_chord = FALSE,
title1_found = FALSE,
debug_mode = FALSE,
need_soc = FALSE,
pagination = 1, /* virtual pages per physical pages */
transpose = 0, /* transposition value */
vpos, /* Current PostScript position, in points */
hpos,
start_of_chorus, /* Vertical positions of the chorus */
end_of_chorus,
chord_size = DEF_CHORD_SIZE, /* Default font size for 'chord_font' */
text_size = DEF_TEXT_SIZE, /* Default font size for 'text_font' */
grid_size = DEF_GRID_SIZE,
n_pages = 1, /* total page counter */
v_pages = 1, /* virtual pages */
n_lines = 1, /* line number in input file */
song_pages = 1, /* song page counter */
blank_space = 0; /* consecutive blank line counter */
float
chord_inc,
scale = 1.0, /* Current scale factor */
rotation = 0.0; /* Current rotation */
extern int nb_chord, first_ptr;
extern struct chord_struct chordtab[MAX_CHORD];
extern char *optarg;
extern int optind, opterr;
/* --------------------------------------------------------------------------------*/
use_chord_font() {
printf ("CHORD_FONT setfont\n");
}
/* --------------------------------------------------------------------------------*/
set_chord_font() {
printf ("/CHORD_FONT { /%s findfont %d scalefont } def\n", chord_font, chord_size);
re_encode (chord_font);
}
/* --------------------------------------------------------------------------------*/
use_text_font() {
printf ("TEXT_FONT setfont\n");
}
/* --------------------------------------------------------------------------------*/
set_text_font (int size) {
printf ("/TEXT_FONT { /%s findfont %d scalefont } def\n", text_font, size);
re_encode (text_font);
}
/* --------------------------------------------------------------------------------*/
do_help (char *command) {
fprintf (stderr, "Usage: %s [options] file\n", command);
fprintf (stderr, "Options:\n");
fprintf (stderr, " -c n : set chord size [9]\n");
fprintf (stderr, " -C postsctipt_font : Set chord font\n");
fprintf (stderr, " -t n : set text size [12]\n");
fprintf (stderr, " -T postsctipt_font : set text font\n");
fprintf (stderr, " -g n : set chord grid size [30]\n");
fprintf (stderr, " -l : only print lyrics\n");
fprintf (stderr, " -h : This message\n");
fprintf (stderr, " -2 : 2 pages per sheet\n");
fprintf (stderr, " -4 : 4 pages per sheet\n");
fprintf (stderr, " -d : dumps default chords definitions\n");
fprintf (stderr, " -i file : write table of contents to file\n");
fprintf (stderr, " -a : automatic single space lines without chords\n");
fprintf (stderr, " -p n : starting page number [1]\n");
fprintf (stderr, " -R : odd pages numbers on right\n");
fprintf (stderr, " -L : odd pages numbers on left\n");
}
/* --------------------------------------------------------------------------------*/
do_chord (int i_text, char *chord) {
if (transpose != 0)
if (do_transpose (chord) != 0) {
sprintf (mesg, "Don't know how to transpose [%s]", chord);
error (mesg);
} if (i_text < MAXLINE)
chord_line[i_text] = chordtab[add_to_chordtab (chord)].chord_name;
}
/* --------------------------------------------------------------------------------*/
print_chord_line () {
int i, j; /* Counter */
for (j = 0; j < MAXLINE; j++) {
if (chord_line[j] != NULL) {
use_text_font ();
printf ("(");
for (i = 0; i < j; printf ("%c", text_line[i++]));
printf (") stringwidth pop %d add %d moveto\n", hpos, vpos);
use_chord_font ();
printf ("(%s) show\n", chord_line[j]);
chord_line[j] = NULL;
}
}
}
/* --------------------------------------------------------------------------------*/
do_directive (char *directive) {
int i;
char *command, *comment;
command = (char *) strtok (directive, ": ");
if (!strcmp (command, "start_of_chorus") || !strcmp (command, "soc")) {
/* start_of_chorus = vpos - blank_space; */
need_soc = TRUE;
in_chorus = TRUE;
}
else if (!strcmp (command, "end_of_chorus") || !strcmp (command, "eoc")) {
if (in_chorus) {
end_of_chorus = vpos;
do_chorus_line ();
in_chorus = FALSE;
}
else
error ("Not in a chorus.");
}
else if (!strcmp (command, "textfont") || !strcmp (command, "tf")) {
text_font = (char *) strtok (NULL, ": ");
}
else if (!strcmp (command, "chordfont") || !strcmp (command, "cf")) {
chord_font = (char *) strtok (NULL, ": ");
set_chord_font ();
}
else if (!strcmp (command, "chordsize") || !strcmp (command, "cs")) {
i = atoi ((char *) strtok (NULL, ": "));
if (i == 0)
error ("invalid value for chord_size");
else
chord_size = i;
set_chord_font ();
}
else if (!strcmp (command, "textsize") || !strcmp (command, "ts")) {
i = atoi ((char *) strtok (NULL, ": "));
if (i == 0)
error ("invalid value for text_size");
else
text_size = i;
}
else if (!strcmp (command, "comment") || !strcmp (command, "c")) {
comment = (char *) strtok (NULL, "\0");
advance (blank_space);
blank_space = 0;
advance (text_size);
text_line[i_text] = '\0';
use_text_font ();
printf (".9 setgray\n");
printf ("%d setlinewidth\n", text_size);
printf ("newpath\n");
printf ("%d %d moveto\n", hpos, vpos + text_size / 2 - 2);
printf ("(%s) stringwidth rlineto\n", comment);
printf ("stroke\n");
printf ("%d %d moveto\n", hpos, vpos);
printf ("0 setgray\n");
printf ("1 setlinewidth\n");
printf ("(%s) show\n", comment);
i_text = 0;
}
else if (!strcmp (command, "new_song") || !strcmp (command, "ns")) {
do_new_song ();
}
else if (!strcmp (command, "title") || !strcmp (command, "t")) {
do_title ();
}
else if (!strcmp (command, "subtitle") || !strcmp (command, "st")) {
do_subtitle ();
}
else if (!strcmp (command, "define") || !strcmp (command, "d")) {
do_define_chord ();
}
else {
sprintf (mesg, "Invalid Directive : [%s]", command);
error (mesg);
has_directive = FALSE;
}
}
/* --------------------------------------------------------------------------------*/
do_chorus_line () {
printf ("1 setlinewidth\n");
printf ("newpath\n");
printf ("%d %d moveto\n", L_MARGIN - 10, start_of_chorus);
printf ("0 %d rlineto\n", -(start_of_chorus - end_of_chorus));
printf ("closepath\n");
printf ("stroke\n");
}
/* --------------------------------------------------------------------------------*/
do_translate(float vert, float horiz) {
printf ("%f %f translate\n", vert , horiz );
debug ("changing translation");
}
/* --------------------------------------------------------------------------------*/
do_new_song () {
do_end_of_song ();
nb_chord = first_ptr = 0;
song_pages = 0;
do_start_of_page ();
init_known_chords ();
read_chordrc ();
}
/* --------------------------------------------------------------------------------*/
init_ps () {
printf ("%%!PS-Adobe-1.0\n");
printf ("%%%%Title: A song\n");
printf ("%%%%Creator: Martin Leclerc & Mario Dorion\n");
printf ("%%%%Pages: (atend)\n");
printf ("%%%%BoundingBox: 5 5 605 787\n");
printf ("%%%%EndComments\n");
printf ("/inch {72 mul } def\n");
print_re_encode ();
set_chord_font ();
set_text_font (text_size);
do_init_grid_ps ();
init_known_chords ();
printf ("%%%%EndProlog\n");
printf ("%%%%Page: \"%d\" %d\n", n_pages, n_pages);
printf ("%%%%BeginPageSetup\n");
printf ("/pgsave save def\n");
printf ("%f %f scale\n", scale, scale);
printf ("%f rotate\n", rotation);
printf ("%%%%EndPageSetup\n");
vpos = TOP;
hpos = L_MARGIN;
if (pagination == 4)
do_translate (0.0, 800.0);
else if (pagination == 2)
do_translate (-40.0, -800.0);
}
/* --------------------------------------------------------------------------------*/
do_end_of_song() {
draw_chords();
do_end_of_page();
}
/* --------------------------------------------------------------------------------*/
do_end_of_phys_page () {
debug ("end_of_phys_page");
printf ("pgsave restore\n");
printf ("showpage\n");
printf ("%%%%EndPage: \"%d\" %d\n", n_pages, n_pages);
}
/* --------------------------------------------------------------------------------*/
do_end_of_page () {
printf ("1 setlinewidth\n");
printf ("0 setgray\n");
printf ("newpath\n");
printf ("%d %d 10 sub moveto\n", L_MARGIN, BOTTOM);
printf ("%d 0 rlineto\n", WIDTH - L_MARGIN * 2);
printf ("stroke\n");
if (number_all || song_pages > 1) {
int pnum = (number_all ? page_label : song_pages);
set_text_font (text_size - 2);
use_text_font ();
if (page_label % 2 == left_foot_odd) { /* left side */
printf ("1 inch %d 3 div moveto\n", BOTTOM);
printf ("(Page %d) show\n", pnum);
}
else { /* right side */
printf ("(Page %d) dup stringwidth pop\n", pnum);
printf ("%d exch sub 1 inch sub %d 3 div moveto\n",
WIDTH, BOTTOM);
printf ("show\n");
} if (title1_found) {
printf ("(%s) dup stringwidth pop 2 div\n", title1);
printf ("%d 2 div exch sub %d 3 div moveto\n",
WIDTH, BOTTOM);
printf ("show\n");
} set_text_font (text_size);
} if (in_chorus) {
end_of_chorus = vpos;
do_chorus_line ();
} if (v_pages == pagination) {
do_end_of_phys_page ();
v_pages = 0;
}
}
/* --------------------------------------------------------------------------------*/
do_start_of_page () {
v_pages++;
page_label++;
if (v_pages == 1) {
n_pages++;
printf ("%%%%Page: \"%d\" %d\n", n_pages, n_pages);
printf ("%%%%BeginPageSetup\n");
printf ("/pgsave save def\n");
printf ("%f %f scale\n", scale, scale);
printf ("%f rotate\n", rotation);
printf ("%%%%EndPageSetup\n");
} if (pagination == 4) {
if (v_pages == 1)
do_translate (0.0, 800.0);
else if (v_pages == 2)
do_translate (600.0, 0.0);
else if (v_pages == 3)
do_translate (-600.0, -800.0);
else if (v_pages == 4)
do_translate (600.0, 0.0);
} if (pagination == 2) {
if (v_pages == 1)
do_translate (-40.0, -800.0);
else if (v_pages == 2)
do_translate (500.0, 0.0);
} vpos = TOP;
hpos = L_MARGIN;
song_pages++;
if (in_chorus) {
start_of_chorus = vpos;
}
}
/* --------------------------------------------------------------------------------*/
advance (int amount) {
vpos = vpos - amount; /* Affect text positionning ! */
if (vpos < BOTTOM) {
do_end_of_page ();
do_start_of_page ();
}
}
/* --------------------------------------------------------------------------------*/
print_text_line () {
int i;
text_line[i_text] = '\0';
for (i = 0; text_line[i] == ' '; i++);
if (!(lyrics_only || auto_space && !has_chord)) {
advance (blank_space);
blank_space = 0;
advance (chord_size + 1);
if ((text_line[i] != '\0')
&& (vpos - text_size <= BOTTOM))
advance (text_size);
if (need_soc) {
start_of_chorus = vpos + chord_size;
need_soc = FALSE;
} print_chord_line ();
} if (text_line[i] == '\0') {
blank_space += text_size - 2;
debug ("blank line found ");
}
else {
advance (blank_space);
blank_space = 0;
advance (text_size - 1);
if (need_soc) {
start_of_chorus = vpos + text_size;
need_soc = FALSE;
} use_text_font ();
printf ("%d %d moveto\n", hpos, vpos);
printf ("(%s) show\n", text_line);
} i_text = 0;
i_text_ov = FALSE;
hpos = L_MARGIN;
has_chord = FALSE;
}
/* --------------------------------------------------------------------------------*/
do_title () {
char *buf;
buf = (char *) strtok (NULL, "\0");
set_text_font (text_size + 5);
use_text_font ();
printf ("(%s) dup stringwidth pop 2 div\n", buf);
printf ("%d 2 div exch sub %d moveto\n", WIDTH, vpos);
printf ("show\n");
vpos = vpos - text_size - 5;
strcpy (title1, buf);
title1_found = TRUE;
set_text_font (text_size);
if (toc_file && song_pages == 1) { /* generate index entry *//* careful to ignore any \ which may have been inserted */
char *bp;
for (bp = buf; *bp; bp++)
if (*bp != '\\')
putc (*bp, toc_file);
fprintf (toc_file, " ... %d\n", page_label);
}
}
/* --------------------------------------------------------------------------------*/
do_subtitle() {
char *buf;
buf = (char *)strtok(NULL, "\0");
use_text_font();
printf ("(%s) dup stringwidth pop 2 div\n", buf);
printf ("%d 2 div exch sub %d moveto\n", WIDTH , vpos);
printf ("show\n");
vpos = vpos - text_size ;
}
/* --------------------------------------------------------------------------------*/
put_in_string ( unsigned char array[MAXLINE], int *p_index, unsigned char c,
int max_index, int *p_ov_flag) {
if (*p_index < max_index) {
if ((int) c < 128) {
array[(*p_index)++] = c;
}
else {
array[(*p_index)++] = '\\';
sprintf ((char *) &array[*p_index], "%o", c);
(*p_index) += 3;
}
}
else {
if (!*p_ov_flag) {
error ("Buffer Overflow");
*p_ov_flag = TRUE;
}
}
}
/* --------------------------------------------------------------------------------*/
process_file (FILE * source_fd) {
debug ("start of process_file");
n_lines = 0;
while ((c = getc (source_fd)) != EOF) {
i_input++;
switch ((char) c) {
case '[':
if (in_chord)
error ("Opening a chord within a chord!");
else
in_chord = TRUE;
i_chord = 0;
break;
case ']':
if (in_chord) {
in_chord = FALSE;
chord[i_chord] = '\0';
do_chord (i_text, chord);
has_chord = TRUE;
i_chord = 0;
i_chord_ov = FALSE;
}
else
error ("']' found with no matching '['");
break;
case '{':
in_directive = TRUE;
i_directive = 0;
has_directive = TRUE;
break;
case '}':
if (in_directive) {
in_directive = FALSE;
directive[i_directive] = '\0';
for (; (c = getc (source_fd)) != '\n';);
i_input = 0;
do_directive (directive);
has_directive = FALSE;
n_lines++;
i_directive = 0;
i_directive_ov = FALSE;
}
else
error ("'}' found with no matching '{'");
break;
case '\n':
if (in_directive)
error ("Line ends while in a directive !");
if (in_chord)
error ("Line ends while in a chord !");
if (has_directive == FALSE) {
if (in_chordrc)
error ("line is NOT a directive");
else {
print_text_line ();
}
}
else
has_directive = FALSE;
n_lines++;
i_input = 0;
in_directive = FALSE;
in_chord = FALSE;
break;
case '(':
case ')':
if (in_directive) {
put_in_string (directive, &i_directive, '\\', MAXTOKEN, &i_directive_ov);
put_in_string (directive, &i_directive, c, MAXTOKEN, &i_directive_ov);
break;
}
else if (in_chord) { /* allow parens in chord names */
put_in_string (chord, &i_chord, '\\', MAXLINE, &i_text_ov);
put_in_string (chord, &i_chord, c, MAXLINE, &i_text_ov);
break;
}
else {
put_in_string (text_line, &i_text, '\\', MAXLINE, &i_text_ov);
put_in_string (text_line, &i_text, c, MAXLINE, &i_text_ov);
break;
} /* This case HAS to be the last before the default statement !!! */ case '#':
if (i_input == 1) {
for (; (c = getc (source_fd)) != '\n';);
n_lines++;
i_input = 0;
break;
} default:
if (in_chord) {
if (c != ' ')
put_in_string (chord, &i_chord, c, MAXTOKEN, &i_text_ov);
}
else if (in_directive) {
put_in_string (directive, &i_directive, c, MAXTOKEN, &i_directive_ov);
}
else {
put_in_string (text_line, &i_text, c, MAXLINE, &i_text_ov);
} break;
}
} print_text_line ();
}
/* --------------------------------------------------------------------------------*/
read_input_file () {
current_file = source;
source_fd = fopen (source, "r");
if (source_fd == NULL) {
fprintf (stderr, "Unable to open [%s]\n", source);
exit (1);
} process_file (source_fd);
fclose (source_fd);
}
/* --------------------------------------------------------------------------------*/
read_chordrc () {
char chordrc[MAXTOKEN];
FILE *chordrc_fd;
int n_lines_save;
strcpy (chordrc, "s:.chordrc");
current_file = chordrc;
chordrc_fd = fopen (chordrc, "r");
if (chordrc_fd != NULL) {
n_lines_save = n_lines;
n_lines = 1;
in_chordrc = TRUE;
process_file (chordrc_fd);
in_chordrc = FALSE;
n_lines = n_lines_save;
fclose (chordrc_fd);
} current_file = source;
}
/* --------------------------------------------------------------------------------*/
debug(char *dbg_str) {
if (debug_mode)
fprintf (stderr, "Debug: %s\n", dbg_str);
}
/* --------------------------------------------------------------------------------*/
print_version() {
char *version = VERSION;
char *patch_level = PATCH_LEVEL;
printf ("chord version %s, patchlevel %s\n", version, patch_level);
}
/* --------------------------------------------------------------------------------*/
error(char *err_str) {
fprintf(stderr, "WARNING: %s\n",err_str);
fprintf(stderr, " in file %s, line %d\n", current_file,n_lines);
}
/* --------------------------------------------------------------------------------*/
main (int argc, char **argv)
{
int c, i;
while ((c = getopt (argc, argv, "hlDd24Vc:t:g:C:T:x:aLRp:i:")) != -1)
switch (c) {
case 'h':
do_help (argv[0]);
exit (1);
break;
case 'D':
debug_mode = TRUE;
break;
case 'd':
init_known_chords ();
dump_chords ();
exit (0);
case 'c':
i = atoi (optarg);
if (i == 0)
error ("invalid value for chord_size");
else
chord_size = i;
break;
case 't':
i = atoi (optarg);
if (i == 0)
error ("invalid value for text_size");
else
text_size = i;
break;
case 'x':
i = atoi (optarg);
if (i == 0)
error ("invalid value for transposition");
else
transpose = i;
break;
case 'T':
text_font = optarg;
break;
case 'C':
chord_font = optarg;
break;
case 'g':
i = atoi (optarg);
if (i == 0)
error ("invalid value for grid_size");
else
grid_size = i;
break;
case 'l':
lyrics_only = TRUE;
break;
case 'V':
print_version ();
exit (0);
case '2':
pagination = 2;
scale = scale2;
rotation = 90.0;
break;
case '4':
pagination = 4;
scale = scale4;
break;
case 'i':
if (!strcmp (optarg, "-"))
toc_file = stderr;
else
toc_file = fopen (optarg, "w");
if (toc_file == NULL) {
perror (optarg);
error ("unable to create index file");
} break;
case 'a':
auto_space = TRUE;
break;
case 'p':
page_label = atoi (optarg);
number_all = TRUE;
break;
case 'L':
left_foot_odd = 1;
break;
case 'R':
left_foot_odd = 0;
break;
case '?':
do_help (argv[0]);
break;
} /* File Processing */ init_ps ();
read_chordrc ();
chord_inc = chord_size * 1.5;
if (optind == argc) {
debug ("Reading stdin");
strcpy (source, "stdin");
process_file (stdin);
}
else {
for (; optind < argc; optind++) {
debug ("Processing a file");
strcpy (source, argv[optind]);
read_input_file ();
if (optind < argc - 1)
do_new_song ();
}
} do_end_of_song ();
if (v_pages != 0) {
do_end_of_phys_page ();
} printf ("%%%%Trailer\n");
printf ("%%%%Pages: %d 1\n", n_pages);
printf ("%%%%EOF\n");
if (toc_file)
fclose (toc_file);
exit (0);
return (0);
}